#include "hspell.h"
#include <QtCore/QDebug>
#include <QtCore/QRegExp>



//--------------------------------------------------
/**
 * @brief HSpell::HSpell
 */

HSpell::HSpell () : QSettings ("PapaJaac", "hspell")
{

	if (! QDir (dicPath ()).exists ())
	{
		QDir dir;
		dir.mkpath (dicPath ());
	}

	QString affDest (QString ("%1%2.aff")
					 .arg (dicPath ())
					 .arg (currentAff ()));

	if (! QFile (affDest).exists ())
	{
		setCurrentAff ("fr-classique+reforme1990");
		QString affSrc (":/hdics/fr-classique+reforme1990.aff");
		QFile::copy (affSrc, affDest);
		QFile::setPermissions (affDest, QFile::ReadUser| QFile::WriteUser);
		affDest = QString ("%1%2.aff")
				  .arg (dicPath ())
				  .arg (currentAff ());
	}

	QString dicDest (QString ("%1%2.dic")
					 .arg (dicPath ())
					 .arg (currentDic ()));

	if (! QFile (dicDest).exists ())
	{
		setCurrentDic ("fr-classique+reforme1990");
		QString dicSrc (":/hdics/fr-classique+reforme1990.dic");
		QFile::copy (dicSrc, dicDest);
		QFile::setPermissions (dicDest, QFile::ReadUser| QFile::WriteUser);
		dicDest = QString ("%1%2.dic")
				  .arg (dicPath ())
				  .arg (currentDic ());
	}

	m_handle = Hunspell_create (affDest.toUtf8 ().constData (), dicDest.toUtf8 ().constData ());

}
//-----------------
/**
 * @brief HSpell::~HSpell
 */
HSpell::~HSpell ()
{
	Hunspell_destroy (m_handle);
}
//-------------------------------------
/**
 * @brief HSpell::spell
 * @param word
 * @return
 */
int HSpell::spell(const QString &word)
{
	return Hunspell_spell (m_handle, word.toUtf8 ().constData ());
}
//-------------------------------------------
/**
 * @brief HSpell::isUnknown
 * @param word
 * @return
 */
bool HSpell::isUnknown(const QString &word)
{
	return spell (word) == 0;
}
//-------------------------------
/**
 * @brief HSpell::dicList
 * @return
 */
QStringList HSpell::dicList ()
{
	QDir dir (dicPath ());

	QStringList filters;
	filters << "*.dic";
	dir.setNameFilters(filters);
	QFileInfoList list (dir.entryInfoList ());

	QStringList result;
	foreach (QFileInfo info, list)
		result << info.baseName ();

	return result;
}
//-----------------------------------------------
/**
 * @brief HSpell::analyse
 * @param word
 * @return
 */
QStringList HSpell::analyse (const QString& word)
{
	char** slst;
	int count = Hunspell_analyze (m_handle, &slst, word.toUtf8 ().constData ());
	QStringList result;

	for (int indice = 0 ; indice < count ; indice++)
	{
		result << QString (slst [indice]);
	}
	return result;
}
//---------------------------------------------
/**
 * @brief HSpell::stem
 * @param word
 * @return
 */
QStringList HSpell::stem (const QString& word)
{
	char** slst;
	int count = Hunspell_stem (m_handle, &slst, word.toUtf8 ().constData ());
	QStringList result;

	for (int indice = 0 ; indice < count ; indice++)
	{
		result << QString (slst [indice]);
	}
	return result;
}
//----------------------------------------------
QStringList HSpell::stem2 (const QString& word)
{
	QStringList list (analyse (word));

	int n = list.size ();
	char* desc [n];
	for (int indice = 0 ; indice < list.size () ; indice++)
	{
		desc [indice] = list.at(indice).toUtf8 ().data ();
	}

	char ** slst;
	int count = /*Hunspell_stem2 (m_handle, &slst, desc, n);*/ 0;

	QStringList result;

	for (int indice = 0 ; indice < count ; indice++)
	{
		result << QString (slst [indice]);
	}
	return result;

}
//---------------------
void HSpell::generate()
{
	//	int result = Hunspell_generate (m_handle, slst, word, word2);
}
//------------------------
void HSpell::generate2 ()
{
	//	int result = Hunspell_generate2 (m_handle, slst, word, desc, n);
}
//-------------------------------------
void HSpell::add (const QString& word)
{
	Hunspell_add (m_handle, word.toUtf8 ().constData ());
}
//---------------------------
void HSpell::addWithAffix ()
{
	//	int result = Hunspell_add_with_affix (m_handle, word, example);
}
//----------------------------------------
/**
 * @brief HSpell::remove
 * @param word
 */
void HSpell::remove (const QString& word)
{
	Hunspell_remove (m_handle, word.toUtf8 ().constData ());
}
//----------------------
// Correction de texte
//----------------------
/**
 * @brief HSpell::replaced
 * @param text
 * @param bad
 * @param good
 * @return
 */
QString HSpell::replaced (const QString &text, const QString &bad, const QString &good)
{
	static const QString format ("\\b%1\\b");

	const QString& badToLower (bad.toLower ());
	const QString& badToUpper (bad.toUpper ());
	const QString& badToFirstCap (badToUpper.at (0) + badToLower.mid (1));

	const QString& goodToLower (good.toLower ());
	const QString& goodToUpper (good.toUpper ());
	const QString& goodToFirstCap (goodToUpper.at (0) + goodToLower.mid (1));

	QString result (text);

	QRegExp regExp (format.arg (badToLower));
	result.replace (regExp, goodToLower);

	regExp.setPattern (format.arg (badToUpper));
	result.replace (regExp, goodToUpper);

	regExp.setPattern (format.arg (badToFirstCap));
	result.replace (regExp, goodToFirstCap);

	return result;
}

//---------------------------
// SETTINGS
//---------------------------

/**
 * @brief HSpell::currentDic
 * @return
 */
QString HSpell::currentDic ()
{
	return value ("currentDic", QString ("fr-classique+reforme1990")).toString ();
}
//--------------------------------------------
/**
 * @brief HSpell::setCurrentDic
 * @param dic
 */
void HSpell::setCurrentDic (const QString &dic)
{
	setValue ("currentDic", dic);
}
//---------------------------
/**
 * @brief HSpell::currentAff
 * @return
 */
QString HSpell::currentAff ()
{
	return value ("currentAff", QString ("fr-classique+reforme1990")).toString ();
}
//--------------------------------------------
/**
 * @brief HSpell::setCurrentAff
 * @param aff
 */
void HSpell::setCurrentAff (const QString &aff)
{
	setValue ("currentAff", aff);
}
//----------------------------------------------------
/**
 * @brief HSpell::suggestionsFor
 * @param word
 * @return
 */
QStringList HSpell::suggestionsFor (const QString &word)
{
	char ** slst;
	int count = Hunspell_suggest (m_handle, &slst, word.toUtf8 ().constData ());
	QStringList result;

	for (int indice = 0 ; indice < count ; indice++)
	{
		result << QString (slst [indice]);
	}

	return result;
}
//--------------------------------------------------------
/**
 * @brief HSpell::misspelledWords
 * @param text
 * @return
 */
QStringList HSpell::misspelledWords (const QString &text)
{
	const QStringList words (text.simplified ().split (QRegExp ("\\b"), QString::SkipEmptyParts)); // liste des mots

	QSet<QString> result;

	foreach (const QString& word, words) {
		if (isUnknown (word)) {
			result << word;
		}
	}

	return result.toList ();
}
